package com.zc.manager.device.events.handler;

import com.zc.manager.device.domain.IotProduct;
import com.zc.manager.device.service.IIotProductService;
import com.zc.supports.official.JetLinksDeviceMetadataCodec;
import lombok.extern.slf4j.Slf4j;
import com.zc.manager.device.events.DeviceProductDeployEvent;
import com.zc.manager.device.service.data.DeviceDataService;
import com.zc.core.metadata.DeviceMetadataCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 处理设备产品发布事件
 *
 * @author bsetfeng
 * @author zhouhao
 * @since 1.0
 **/
@Component
@Slf4j
@Order(1)
public class DeviceProductDeployHandler implements CommandLineRunner {

    private final IIotProductService productService;

    private final DeviceMetadataCodec codec = new JetLinksDeviceMetadataCodec();

    private final DeviceDataService dataService;


    @Autowired
    public DeviceProductDeployHandler(IIotProductService productService,
                                      DeviceDataService dataService) {
        this.productService = productService;
        this.dataService = dataService;
    }


    @EventListener
    public void handlerEvent(DeviceProductDeployEvent event) {
        event.async(
            this
                .doRegisterMetadata(event.getId(), event.getMetadata())
        );
    }

    /**
     * 注册产品元数据
     * @param productId 产品ID
     * @param metadataString 元数据
     * @return
     */
    private Mono<Void> doRegisterMetadata(String productId, String metadataString) {
        return codec
            .decode(metadataString)
            .flatMap(metadata -> dataService.registerMetadata(productId, metadata));
    }


    @Override
    public void run(String... args) {

        //启动时发布物模型
        IotProduct iotProduct = new IotProduct();
        iotProduct.setPublishState(IotProduct.PUBLISH);

        Flux.fromIterable(productService.selectIotProductList(iotProduct))
                .flatMap(product -> this
                        .doRegisterMetadata(product.getId(), product.getMetadata())
                        .onErrorResume(err -> {
                            log.warn("register product metadata error", err);
                            return Mono.empty();
                        })
                )
                .subscribe();
    }
}
